import { get, set } from 'xe-utils'
import type { Entries } from 'type-fest'
import { isArray } from './types'
import type { Arrayable } from '.'

export const keysOf = <T extends object>(arr: T) => Object.keys(arr) as Array<keyof T>
export const entriesOf = <T extends object>(arr: T) => Object.entries(arr) as Entries<T>
export { hasOwn } from '@vue/shared'

export const getProp = <T = any>(
  obj: Record<string, any>,
  path: Arrayable<string>,
  defaultValue?: any,
): { value: T } => {
  return {
    get value() {
      return get(obj, path, defaultValue)
    },
    set value(val: any) {
      set(obj, path, val)
    },
  }
}

type List<T> = ArrayLike<T>
type PropertyName = string | number | symbol
interface Dictionary<T> {
  [index: string]: T
}
export function fromPairs<T>(pairs: List<[PropertyName, T]> | null | undefined): Dictionary<T> {
  if (!isArray(pairs)) return {}
  let index = -1
  const length = pairs == null ? 0 : pairs.length
  const result: Dictionary<T> = {}

  while (++index < length) {
    const pair = pairs[index]
    result[pair[0]] = pair[1]
  }
  return result
}
